package storage

import (
	"sync"
	"time"
)

// EntryOption 缓存项选项, 用于配置缓存行为, 如过期时间、标签等
type EntryOption struct {
	Expire  time.Duration // 过期时间, 最小为 1秒, 0 表示不过期, 默认为 Cache Driver => DefaultExpire
	Tags    []string      // 缓存 Tags 标签
	Timeout time.Duration // 超时时间, 最小为 1 秒, 默认为 3s (部分场景使用, 如: LoadDo, UpdateFn 等场景使用)
}

// EntryOptions 缓存项选项, 用于配置缓存行为, 如过期时间、标签等
type EntryOptions func(*EntryOption)

// 默认超时时间, 默认为3s
const entryDefaultTimeout = time.Second * 3

var entryOptionsPool = sync.Pool{
	New: func() any {
		return &EntryOption{Tags: make([]string, 0, 3)}
	},
}

// GetEntryOptionsFromPool 从 Options 池获取一个新的 Option 对象, 并重置其值
func GetEntryOptionsFromPool() *EntryOption {
	op := entryOptionsPool.Get().(*EntryOption)
	op.reset()
	return op
}
func (o *EntryOption) reset() {
	o.Expire = 0
	o.Tags = o.Tags[:0]
	o.Timeout = entryDefaultTimeout
}

// Release 回收 Option 对象到 Options 池, 并重置其值, 以便下次使用
func (o *EntryOption) Release() {
	if o != nil {
		o.reset()
		entryOptionsPool.Put(o)
	}
}

// WithTags 设置缓存 Tags 标签, 可以设置多个标签, 默认为空切片 []string{}
func WithTags(tags ...string) EntryOptions {
	return func(o *EntryOption) {
		if len(tags) > 0 {
			o.Tags = append(o.Tags, tags...)
		}
	}
}

// WithExpire 设置过期时间, 最小为1秒, 0 表示不过期, 默认为 Cache Driver => DefaultExpire
func WithExpire(expire time.Duration) EntryOptions {
	return func(o *EntryOption) {
		if expire <= 0 {
			o.Expire = 0
		} else if expire < time.Second {
			o.Expire = time.Second
		} else {
			o.Expire = expire
		}
	}
}

// WithTimeout 设置超时时间, 最小为1秒, 默认为3s (部分场景使用, 如: LoadDo, UpdateFn 等场景使用), 默认为3s
func WithTimeout(timeout time.Duration) EntryOptions {
	return func(o *EntryOption) {
		if timeout <= 0 {
			o.Timeout = entryDefaultTimeout
		} else if timeout < time.Second {
			o.Timeout = time.Second
		} else {
			o.Timeout = timeout
		}
	}
}
